package com.sec.android.app.myfiles.feature;

import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.UserHandle;
import android.text.TextUtils;
import android.view.View;

import com.sec.android.app.myfiles.facade.MyFilesFacade;
import com.sec.android.app.myfiles.facade.cmd.SpinnerProgressCmd;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.info.AppFeatures;
import com.sec.android.app.myfiles.module.ModuleLoader;
import com.sec.android.app.myfiles.module.abstraction.AbsDragAndDrop;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.StorageType;
import com.sec.android.app.myfiles.navigation.NavigationInfo;
import com.sec.android.app.myfiles.operation.FileOperationArgs;
import com.sec.android.app.myfiles.operation.FileOperator;
import com.sec.android.app.myfiles.operation.ProgressListener;
import com.sec.android.app.myfiles.util.FileUtils;
import com.sec.android.app.myfiles.util.SemFwWrapper;
import com.sec.android.app.myfiles.util.StorageMonitor;
import com.sec.android.app.myfiles.util.UiUtils;
import com.sec.android.app.myfiles.widget.listview.AbsListViewImp;

import java.util.ArrayList;
import java.util.HashMap;

public class DragAndDropMgr {

    public static final String DRAG_DROP_MYFILES_LOCAL = "selectedUri";
    public static final String DRAG_DROP_MYFILES_CLOUD = "selectedCloudUri";
    public static final String DRAG_DROP_GALLERY_LOCAL = "galleryURI";
    public static final String DRAG_DROP_GALLERY_CLOUD = "galleryCloudURI";
    public static final String DRAG_DROP_LABEL_SIDE_SYNC = "startSideSyncDrag";
    public static final String DRAG_DROP_SOURCE_IS_SECURE_FOLDER = "sourceIsSecureFolder";

    private AbsDragAndDrop mDragDrop;
    private AbsMyFilesFragment mFragment;
    private static ArrayList<FileRecord> mSourceList = null;
    private HashMap<StorageType, AbsDragAndDrop> mDragDropMap = new HashMap<>();

    public boolean supportDragAndDrop(AbsMyFilesFragment fragment) {
        boolean bRet = false;
        NavigationInfo currentInfo = fragment.getNavigationInfo();
        if (currentInfo != null && !UiUtils.isCategoryFolderList(currentInfo.getCurRecord())) {
            if (AppFeatures.isTabletUIMode()) {
                if (!currentInfo.isSelectMode()) {
                    bRet = true;
                }
            } else { // Phone
                if (currentInfo.getStorageType() != StorageType.Recent) {
                    int processId = fragment.getProcessId();
                    MultiWindowMgr multiMgr = MultiWindowMgr.getInstance(fragment.getActivity(), processId);
                    if (multiMgr.isMultiWindow()) {
                        bRet = true;
                    }
                    if (SidesyncMgr.getInstance().isConnected(mFragment.context())) {
                        bRet = true;
                    }
                }
            }
        }
        return bRet;
    }

    public DragAndDropMgr(AbsMyFilesFragment fragment, StorageType storageType) {
        getDragDropImp(fragment, storageType, null);
        mFragment = fragment;
    }

    public DragAndDropMgr(AbsMyFilesFragment fragment, StorageType storageType, AbsListViewImp listView) {
        getDragDropImp(fragment, storageType, listView);
        mFragment = fragment;
    }

    private void getDragDropImp(AbsMyFilesFragment fragment, StorageType storageType, AbsListViewImp listView) {
        mDragDrop = mDragDropMap.get(storageType);
        if (mDragDrop == null) {
            mDragDrop = ModuleLoader.getInstance().createDragAndDropImp(fragment, storageType, listView);
            mDragDropMap.put(storageType, mDragDrop);
        }
    }

    public void attachDragListenerToView(View view) {
        if (mDragDrop != null && view != null) {
            view.setOnDragListener(mDragDrop);
        }
    }

    public void startDrag(View view, ArrayList<FileRecord> recordList, FileRecord curRecord) {
        if (mDragDrop != null) {
            if (SidesyncMgr.getInstance().isConnected(mFragment.context()) && !SidesyncMgr.getInstance().isSlinkConnected(mFragment.context())) {
                SidesyncMgr.getInstance().onDragListToSidesync(mFragment.context(), recordList);
            } else if (supportDragAndDrop(mFragment)) {
                mDragDrop.doDrag(view, recordList, curRecord);
                mSourceList = recordList;
            }
        }
    }

    public boolean isDragStart() {
        boolean bRet = false;

        if (mDragDrop != null) {
            bRet = mDragDrop.isDragStart();
        }

        return bRet;
    }

    public void setDragStart(boolean dragStart) {
        if (mDragDrop != null) {
            mDragDrop.setDragStart(dragStart);
        }
    }

    public static boolean isDragAndDropAvailable(String source, String destination) {
        if (TextUtils.isEmpty(source) || TextUtils.isEmpty(destination)) {
            return false;
        }

        if (!StorageMonitor.isCurrentStoragePath(source) || !(StorageMonitor.isCurrentStoragePath(destination) || (StorageMonitor.isCloudPath(destination)))) {
            return false;
        }

        /*private -> non private do not support*/
        /*private <- non private support*/
        return !FileUtils.isPrivateFolder(source) || (FileUtils.isPrivateFolder(source) && FileUtils.isPrivateFolder(destination));
    }

    public static void convertDragItems(AbsMyFilesFragment fragment, Context mContext, ProgressListener listener, ClipData clipData, FileRecord dstFile) {
        MyFilesFacade.execSpinnerProgress(fragment.mProcessId, mContext, SpinnerProgressCmd.OperationProgress.SHOW);
        FileOperationArgs args = new FileOperationArgs();
        args.mProcessId = fragment.getProcessId();
        args.mFragment = fragment;
        args.mDst = dstFile;
        args.mClipData = clipData;
        FileOperator fileOperator = new FileOperator(fragment.getProcessId(), mContext, fragment.getFragmentManager(), null);
        fileOperator.registerProgressListener(listener, null);
        fileOperator.setOperationArgs(FileOperator.Operation.CONVERT_DRAG_ITEM, args);
        fileOperator.execute();
    }

    public static boolean canDrop(Context context, ClipData clipData, FileRecord dstFile) {
        boolean bRet = false;
        if ((clipData != null) && (clipData.getDescription() != null) && (clipData.getDescription().getLabel() != null)) {
            if (!(clipData.getDescription().getLabel().equals("Multiwindow drag and drop image"))
                    && !(clipData.getDescription().getLabel().equals("Multiwindow drag and drop text"))) {
                bRet = true;
            }
            if (DRAG_DROP_MYFILES_LOCAL.equals(clipData.getDescription().getLabel())) {
                String selectedFilePath = FileUtils.getClipDataFilePath(context, clipData.getItemAt(0));
                if (!isDragAndDropAvailable(selectedFilePath, dstFile.getFullPath())) {
                    bRet = false;
                }
            }
            if (DRAG_DROP_SOURCE_IS_SECURE_FOLDER.equals(clipData.getDescription().getLabel())) {
                bRet = KnoxMgr.getInstance(context).isSecureFolder();
            }
        }
        if (bRet && FileOperator.isWorking()) {
            bRet = false;
        }
        return bRet;
    }

    public static boolean canDrop(Context context, ClipDescription description) {
        boolean bRet = true;
        if ((description != null) && (description.getLabel() != null)) {
            bRet = !(DRAG_DROP_SOURCE_IS_SECURE_FOLDER.equals(description.getLabel()) && !KnoxMgr.getInstance(context).isSecureFolder());
        }
        if (bRet && FileOperator.isWorking()) {
            bRet = false;
        }
        return bRet;
    }

    public static ArrayList<FileRecord> getSourceList() {
        return mSourceList;
    }

    public static void clearSourceList() {
        if (mSourceList != null) {
            mSourceList.clear();
            mSourceList = null;
        }
    }

    public static boolean checkUserChange(Context context, FileRecord dstFile, Uri uri) {
        String user = FileUtils.getUserInfoFromUri(uri);
        String me = String.valueOf(SemFwWrapper.semGetMyUserId());
        if (!TextUtils.isEmpty(user) && !user.equals(me) && AppFeatures.isKnox()) {
            Intent intent = new Intent(KnoxMgr.ACTION_MOVE_BY_DND);
            intent.putExtra(KnoxMgr.EXTRA_USER_ID, SemFwWrapper.semGetMyUserId());
            intent.putExtra(KnoxMgr.EXTRA_DEST_PATH, dstFile.getFullPath());
            return true;
        }
        return false;
    }
}
